﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Collections;
using System.IO;

namespace Com.Guocz.Media.FileSystem
{
    public class Path : ISerializable
    {
        public bool IsDirectory { get; set; }

        public bool Tag { get; set; }
        public Path Father { get; set; }
        private IDictionary<string, Path> children = new Dictionary<string, Path>();

        public Path FirstFile
        {
            get
            {
                if (children.Count > 0)
                {
                    foreach (var item in children)
                    {
                        if (!item.Value.IsDirectory)
                        {
                            return item.Value;
                        }
                    }
                }

                return null;
            }
        }
        public string AbsolutePath
        {
            get
            {
                if (Father != null)
                {
                    return (Father.AbsolutePath + Const.SEPARATOR + Name).Replace(@"//", @"/") ;
                }
                else
                {
                    return Const.SEPARATOR;
                }
            }
        }
        public List<Path> Children
        {
            get
            {
                List<Path> tmp = new List<Path>();
                tmp.AddRange(children.Values);
                return tmp;
            }
        }
        public string Name
        {
            get;
            set;
        }

        public Path(string name)
        {
            IsDirectory = true;
            Name = name;
        }

        public Path()
        {
            IsDirectory = true;
            Name = "tmp";
        }

        private IList<BlockMetaInfo> blocks = new List<BlockMetaInfo>();

        public IList<BlockMetaInfo> BlockMetaList
        {
            get
            {
                return blocks;
            }
        }
        public void InitBlockList(IList<BlockMetaInfo> blockList)
        {
            if (blocks == null)
            {
                blocks = new List<BlockMetaInfo>();
            }
            foreach (var item in blockList)
            {
                blocks.Add(item);
            }
        }

        #region ISerializable Members

        public void readField(System.IO.BinaryReader input)
        {
            Name = input.ReadString();
            IsDirectory = input.ReadBoolean();
            
            if (IsDirectory)
            {
                int childCount = input.ReadInt32();
                for (int i = 0; i < childCount; i++)
                {
                    Path p = new Path();
                    p.readField(input);
                    children[p.Name] = p;
                    p.Father = this;
                }
            }
            else
            {
                int blockCount = input.ReadInt32();
                for (int i = 0; i < blockCount; i++)
                {
                    BlockMetaInfo blockMeta = new BlockMetaInfo();
                    blockMeta.readField(input);
                    blocks.Add(blockMeta);
                }
            }
            try
            {
                Tag = input.ReadBoolean();
            }
            catch (IOException)
            {
                Tag = false;
            }
        }

        public void writeField(System.IO.BinaryWriter output)
        {
            output.Write(Name);
            output.Write(IsDirectory);
            
            if (IsDirectory)
            {
                output.Write(children.Count);
                foreach (var child in children.Values)
                {
                    child.writeField(output);
                }
            }
            else
            {
                output.Write(blocks.Count);
                foreach (var block in blocks)
                {
                    block.writeField(output);
                }
            }
            output.Write(Tag);
        }

        #endregion

        internal void AddChild(Path p)
        {
            children[p.Name] = p;
        }

        internal Path GetChild(string name)
        {
            if (children.ContainsKey(name))
            {
                return children[name];
            }
            return null;
        }

        internal void rename(string srcname, string desname)
        {
            Path old = children[srcname];
            children.Remove(srcname);
            old.Name = desname;
            children[desname] = old;
        }

        internal void DeleteChild(string p)
        {
            children.Remove(p);
        }
    }
}
